const pools = require("./pools");
const CreateSocket = require("./CreateSocket");
async function RzTelnet(cmdArray, flag, realIP,destroySocketFlag) {
  createPool(realIP, flag); //创建一个连接池,存入pools中.key=ip,value=pool
  return new Promise(async (resolve, reject) => {
    try {
      const socket = getSocket(realIP); //从连接池中拿出来一个socket连接
      console.log(`当前socket id=${socket.sid} isConnect=${socket.isConnect} readyState${socket.readyState}`);
      if(socket.destroyed){
        await socket.connect();
        console.log("socket destroyed 连接已经搞定了,即将设置命令行");
      }
      else if (!socket.isConnect) {
        await socket.connect();
        console.log("socket 连接已经搞定了,即将设置命令行");
      } else {
        console.log("socket已经连接了,不需要再次连接");
      }
      socket.setCMDArr(cmdArray);
      socket.startCMD((res)=>{
        if(destroySocketFlag){
          socket.clearCB();
          socket.endSocket(true);
        }
        resolve(res)
      },reject, flag ? 1 << 1 : 1);
    } catch (error) {
      reject(error);
    }
  });
}
async function RZsnmp(ip, cmdArray) {
  return new Promise(async (resolve, reject) => {
    try {
      const dest = new URL(ip);
      const socket = new CreateSocket(dest, true);
      await socket.connect();
      socket.setCMDArr(cmdArray);
      socket.startCMD(resolve,reject, 1 << 2);
    } catch (error) {
      reject(error);
    }
  });
}
const connectOltTimeOutHandler = function (msg) {
  if (msg.indexOf("Can not connect Olt") != -1) {
    return {
      result: false,
      message:'Can not connect Olt',
    };
  }
  return {
    result: true,
    message: "",
  };
};
function createCMD(type) {
  const slice = Array.prototype.slice;
  const f = {
    loginCloudOLT: function (username, password) {
      return [
        {
          expect: /Username:$/gi,
          send: username,
        },
        {
          expect: /Password:$/gi,
          send: password,
        },
      ];
    },
    agentOLT: function (ip, port) {
      return [
        {
          expect: /.*\$$/gi,
          send: `oltconnect ${ip}:${port}`,
          break: true,
          fn:connectOltTimeOutHandler,
        },
      ];
    },
    loginOLT: function (username, password) {
      return [
        {
          out: false,
          expect: /User.*name:$/gi,
          send: username,
        },
        {
          out: false,
          expect: /Password:$/gi,
          send: password,
        },
      ];
    },
    management: function (oltType, mPassword) {
      if (oltType === "ZTE") {
        return [
          {
            out: false,
            expect: />|#$/gi,
            send: "en",
          },
          {
            out: false,
            expect: /Password:|#$/gi,
            send: mPassword||"zxr10",
          },
          {
            out: false,
            expect: /#$/gi,
            send: "terminal length 0",
          },
        ];
      } else if (oltType === "HUAWEI") {
        return [
          {
            out: false,
            expect: />$/gi,
            send: "scroll",
          },
          {
            out: false,
            expect: /:/gi,
            send: " ",
          },
          {
            out: false,
            expect: />$/gi,
            send: "en",
          },
        ];
      } else {
        return [];
      }
    },
    quitOLT: function (oltType) {
      if (oltType === "ZTE") {
        return [
          {
            out: false,
            expect: />|#/gi,
            send: `exit`,
            backToRootLevel: true,
          },
        ];
      } else if (oltType === "HUAWEI") {
        return [
          {
            out: false,
            expect: />|#/gi,
            send: `quit`,
            backToRootLevel: true,
          },
        ];
      }
    },
    quitCloudOLT: function () {
      return [
        {
          out: false,
          expect: /wushupeng\$$/gi,
          send: `exit`,
        },
      ];
    },
  };
  return f[type] && f[type].call(this, ...slice.call(arguments, 1));
}

function getSocket(ip) {
  let pool = pools.get(ip);
  let l = pool.length;
  for (let i = 0; i < l; i++) {
    let result = pool[i];
    if (!result.busy) {
      result.busy=true;
      console.log(`=======================`);
      console.log(`sid=${result.sid};busy=${result.busy};destroyed=${result.socket.destroyed};readyState=${result.socket.readyState}`);
      console.log(`=======================`);
      if(result.socket.destroyed){
        let {ip:oip,realIP,cloudOltState} = result;
        pool.splice(i,1);
        createPool(realIP,cloudOltState);
        result = getSocket(ip);
      }
      return result;
    }
  }
}

function createPool(realIP, cloudOltState) {
  let pool = pools.get(realIP);
  let [hostname,port] = realIP.split(':');
      const dest = {
        hostname,
        port
      }
  if (pool) {
    if(pool.length<4){
      const socket = new CreateSocket(dest, cloudOltState);
      socket.realIP = realIP;
      socket.cloudOltState = cloudOltState;
      pool.push(socket);
    }
    return pool;
  } else {
    pool = new Array();
    while (pool.length <= 3) {      
      const socket = new CreateSocket(dest, cloudOltState);
      socket.realIP = realIP;
      socket.cloudOltState = cloudOltState;
      pool.push(socket);
    }
    pools.set(realIP, pool);
    return pool;
  }
}

function generateCMD(
  loginOLT,
  management,
  bussinessCMD,
  quitOLT,
  quitCloudOLT
) {
  return {
    loginOLT,
    management,
    bussinessCMD,
    quitOLT,
    quitCloudOLT,
  };
}

function generateSnmpCMD(loginCloudOLT, bussinessCMD, quitCloudOLT) {
  return {
    loginCloudOLT,
    agentOLT: [],

    bussinessCMD,
    quitCloudOLT,
  };
}

module.exports = {
  RzTelnet,
  createCMD,
  generateCMD,
  generateSnmpCMD,
  RZsnmp,
};
